// ModelObject.cpp: implementation of the ModelObject class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ModelObject.h"
#include "ModelObserver.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

UE_IMPLEMENT_DYNAMIC(ModelObject, PersistentObject);

ModelObject::ModelObject()
{
	m_nState = eCREATE;
	m_theMatrix.setToIdentity();
	m_GPFTrigger.OwnerPart(this);
	m_bObserverState = FALSE;
	m_bAvailable = TRUE;
}

ModelObject::~ModelObject()
{
}

void ModelObject::AttachFunction(FunctionObject* pFunction)
{
	m_FunctionStack.AddFunction(pFunction);
}

FunctionObject* ModelObject::GetFunction(INT nFunctionID)
{
	FunctionStack::Iterator* pIterator = m_FunctionStack.GetFunction(nFunctionID);
	if(pIterator != NULL)
	{
		ASSERT(pIterator);
		pIterator->Begin();
		FunctionObject* pFunction = NULL;
		pFunction = pIterator->Get();
		delete pIterator;
		return pFunction;
	}
	return NULL;
}

void ModelObject::RemoveFunction(INT nFunctionID)
{
	delete m_FunctionStack.RemoveFunction(nFunctionID);
}

void ModelObject::RemoveAllFunction()
{
}

FunctionStack* ModelObject::GetFunctionStack()
{
	return &m_FunctionStack;
}

PropertySystem::PropertyVariable* ModelObject::GetProperty(const CString& strPropertyName)
{
	return m_PropertyStack.GetProperty(strPropertyName);
}

void ModelObject::RemoveAllProperty()
{
}

void ModelObject::RemoveProperty(const CString& strKey)
{
	m_PropertyStack.Remove(strKey);
}

void ModelObject::AddProperty(PropertySystem::PropertyVariable* pVariable)
{
	ASSERT(pVariable);
	ASSERT(pVariable->GetOwner() == NULL);

	pVariable->SetOwner(this);
	m_PropertyStack.AddProperty(pVariable);
}

PropertySystem::PropertyStack* ModelObject::GetPropertyStack()
{
	return &m_PropertyStack;
}
/*
void ModelObject::AddObserver(ModelObserver* pObserver){
	ASSERT(pObserver);
	if(IsExistObserver(pObserver))
		return;
	pObserver->Model(this);
	m_theObservers.Add(pObserver);
}

void ModelObject::DeleteObserver(ModelObserver* pObserver){
	for(int i = 0; i < m_theObservers.GetSize(); i++)
	{
		if(pObserver == m_theObservers.GetAt(i))
		{
			m_theObservers.RemoveAt(i);
			return;
		}
	}
}

BOOL ModelObject::IsExistObserver(ModelObserver* pObserver)
{
	for(int i = 0; i < m_theObservers.GetSize(); i++)
	{
		if(pObserver == m_theObservers.GetAt(i))
			return TRUE;
	}
	return FALSE;
}

void ModelObject::DeleteAllObserver(){
	m_theObservers.RemoveAll();
}
*/
BOOL ModelObject::IsAllPropertiesKnown()
{
	PropertySystem::PropertyStack::Iterator* pIt = this->m_PropertyStack.NewIterator();
	for(pIt->Begin(); !pIt->End(); pIt->Next())
	{
	}
	delete pIt;
	return TRUE;
}

BOOL ModelObject::IsAllDBPropertiesKnown()
{
	BOOL bResult = TRUE;
	PropertySystem::PropertyStack::Iterator* pIt = this->m_PropertyStack.NewIterator();
	for(pIt->Begin(); !pIt->End(); pIt->Next())
	{
		PropertySystem::PropertyVariable* pVar = static_cast<PropertySystem::PropertyVariable*>(pIt->Get());
		ASSERT(pVar);
		if(pVar->PropertyStyle() == PropertySystem::PropertyVariable::eDB && !pVar->IsKnown())
		{
			bResult = FALSE;
			break;
		}
	}
	delete pIt;
	return bResult;
}

void ModelObject::EffectProperty()
{
	BOOL bIsNeedUpdate = TRUE;
	PropertySystem::PropertyStack::Iterator* pIt = this->m_PropertyStack.NewIterator();
	int nCount = 0;
	while(bIsNeedUpdate)
	{
		bIsNeedUpdate = FALSE;
		for(pIt->Begin(); !pIt->End(); pIt->Next())
		{
			PropertySystem::PropertyVariable* pVar = static_cast<PropertySystem::PropertyVariable*>(pIt->Get());
			ASSERT(pVar);
			ASSERT(pVar->GetOwner());
			if( !pVar->IsKnown() || !pVar->IsEffect())
			{
				pVar->InitValue();
				bIsNeedUpdate = TRUE;
			}
		}
		nCount++;
		if(nCount >= 10)
		{
			ASSERT(FALSE);
			break;
		}
	}
	delete pIt;
}
/*
BOOL ModelObject::UpdateObserver()
{
	for(int i = 0; i < m_theObservers.GetSize(); i++)
	{
		m_theObservers.GetAt(i)->Update();
	}
	return FALSE;
}

ModelObserver* ModelObject::FindObserver(const CString& strObsName)
{
	ModelObserver* pObj = NULL;
	for(int i = 0; i < m_theObservers.GetSize(); i++)
	{
		pObj = m_theObservers.GetAt(i);
		ASSERT(pObj);
		if(pObj->Name() == strObsName)
			return pObj;
	}
	return NULL;
}

void ModelObject::CurObserver(ModelObserver* pObserver)
{
	ASSERT(pObserver);
	m_pCurObserver = pObserver;
}

ModelObserver* ModelObject::CurObserver() const 
{
	ASSERT(m_pCurObserver);
	return m_pCurObserver;
}*/

BOOL ModelObject::operator == (const ModelObject& obj)
{
	if(this == &obj)
		return TRUE;

	PropertySystem::PropertyStack::Iterator* pIt = m_PropertyStack.NewSavePropertyIterator();
	ASSERT_MEMORY_VALID(pIt, FALSE);
	for(pIt->Begin(); !pIt->End(); pIt->Next())
	{
		Variable* pVar = pIt->Get();
		ASSERT(pVar);
		Variable* pVarObj = (*const_cast<ModelObject*>(&obj)).GetProperty(pVar->GetSymbol());
		if((pVarObj == NULL)|| (BOOL)((*pVar)!=(*pVarObj)))
		{
			delete pIt;
			return FALSE;
		}
	}
	delete pIt;

	return TRUE;
}

BOOL ModelObject::IsAvailable() 
{
	return m_bAvailable;
}

void ModelObject::SetAvailable()
{
	m_bAvailable = TRUE;
}

void ModelObject::SetUnavailable()
{
	m_bAvailable = FALSE;
}